Skip to content

E2E: replace login priming with an on-demand lock - #113352

Draft
lucatume wants to merge 5 commits into
trunkfrom
update/e2e-login-lock
Draft

E2E: replace login priming with an on-demand lock#113352
lucatume wants to merge 5 commits into
trunkfrom
update/e2e-login-lock

Conversation

@lucatume

@lucatume lucatume commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Proposed Changes

Why are these changes being made?

The priming list is written by hand per test group. It drifts from what the specs use, an account missing from it gets no priming at all, and a build type carrying the wrong list pays for logins no spec needs. The lock covers the same ground without a list.

Testing Instructions

Three personal builds of E2E Tests (Playwright Test), all on current trunk:

  • 18877035 and 18877473reader__view failed both attempts on both devices, ERR_ABORTED on the goto to /reader. The trace shows Calypso home handing the user to the Dashboard on another host mid-navigation. prime-logins was hiding it.
  • 18877819, with the fix — reader__view green on both devices. The only failures left are plugins__search, stats and invite__new-user, all red on trunk since build Jetpack Connect: Introduce NUX Site User Type step. #31297.

Run 18877819 carried DEBUG=test-account, which prints one line per login. Nine accounts, nine logins, 40 workers reading the cookies instead: defaultUser 1/12, gutenbergSimpleSiteUser 1/10, simpleSiteFreePlanUser 1/7, simpleSitePersonalPlanUser 1/5, atomicUser 1/3, calypsoPreReleaseUser 1/3, three more at 1/0. No worker hit the wait timeout or found an abandoned lock.

Locally, yarn jest --config packages/calypso-e2e/jest.config.js --rootDir packages/calypso-e2e covers the lock: 8 concurrent workers producing one login, release on success and on throw, stale-lock takeover, retry, and the wait ending on freshness.

What a reviewer should check. The waiter's exit condition is hasFreshAuthCookies(), not the cookies file existing: a file left by an earlier run can be there and expired, and waiting on existence hands every waiter a dead session. And the lock is deliberately advisory — a worker whose login outruns the stale window can write cookies while another holds the lock. That costs one duplicate login, which is where every login was before this PR; saveAuthCookies renames its file into place, so no reader sees a torn one.

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • For UI changes, have you tested the affected components in dark mode?
  • Have you tested accessibility for your changes? Ensure the feature remains usable with various user agents (e.g., browsers), interfaces (e.g., keyboard navigation), and assistive technologies (e.g., screen readers) (PCYsg-S3g-p2).
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    • For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages.
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?

@lucatume lucatume self-assigned this Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

Looks like one of the E2E tests has failed.

You can fix them following these steps:

  1. Check out this branch locally:
    gh pr checkout 113352
  2. Start Claude Code in the repo:
    claude
  3. Run the /fix-e2e-tests skill, passing this PR number:
    /fix-e2e-tests 113352
    

@lucatume
lucatume force-pushed the update/e2e-login-lock branch from c59c927 to f428704 Compare August 6, 2026 17:20
Workers share one cookies file per account through COOKIES_PATH, and a CI
build starts with none of them. Every worker misses at once and logs in
concurrently, against a calypso.live container that has just been created.

TestAccount.logInOncePerRun coordinates through a lock directory beside the
cookies: the worker that creates it logs in and writes the cookies, the rest
poll for those cookies and skip the login. A lock older than 90s belongs to a
worker Playwright tore down mid-login and gets taken over by rename, so only
one of several waiters can claim it. A waiter that has waited a minute logs
in unlocked rather than burn its test timeout.

The lock is advisory: nothing stops a worker whose login outran the stale
window from writing cookies anyway. That costs the concurrent login the lock
exists to avoid, which is where every login was before it, and saveAuthCookies
renames its file into place, so a reader never reads a torn one.

authenticate() now saves the cookies it obtains, which it never did: the
accounts reached only through it re-logged-in on every test. It is also the
only place that logs in now, so an account fixture is authenticated when it
is handed over rather than in each spec that remembers to ask.
The setup project logged in as a per-build-type list of accounts before the
suite, so the specs would find cookies rather than all log in at once. The
list is hand written per test group: it drifts from what the specs use, an
account missing from it got no priming at all, and a build type running the
wrong list paid for logins no spec needs. The login lock covers the same
ground without a list.

Removes the project, the env var behind it, the resolver and the reporting
script that read it, the 25 TeamCity parameters setting it and the semicolon
form EXTRA_ENV_VARS grew to carry one. Also the priming half of the legacy
Jest global setup, which has had no specs to prime since the last one moved
to Playwright Test.
Calypso home hands a logged-in user over to the Dashboard on another host,
and that navigation starts after the load event. A spec that authenticates
with waitUntilStable false and navigates straight away raced it and lost:
reader__view failed both its attempts on both devices with ERR_ABORTED on
the goto to /reader, with the Dashboard shell on screen.

The prime-logins project hid this. It logged in as the account before the
suite, so by the time the spec ran the container had served the same pages
already and the hand-over fired earlier than the spec's own navigation.

Such a caller navigates itself next, so authenticate() no longer loads
Calypso home for it, and it waits for the URL to stop changing before it
returns.
@lucatume
lucatume force-pushed the update/e2e-login-lock branch from f428704 to 75acde2 Compare August 10, 2026 10:43
The account fixture ran a full authenticate(), sidebar wait included, so the specs
that pass waitUntilStable: false paid the wait they opt out of and the rest made the
Calypso home trip twice. It stops at the cookies now.

The lock holder removed the lock by path, so a login slower than LOCK_STALE_MS
deleted the lock of the worker that had taken it over and let the others log in at
once. The lock carries its owner's token and only they remove it.

Logging in happens in fixture setup and was charged to the test's own 120s timeout, so
a worker that waited out LOCK_WAIT_MS had under a minute left for the login and the
test both. getAccount hands that time back.

Smaller ones: the first login attempt's error was swallowed and its retry immediate,
the login never dismissed the cookie banner that covers the submit button on mobile
viewports, and the settle wait took a single quiet poll for done and said nothing when
it timed out.
AUTHENTICATE_ACCOUNTS is gone, but saved custom runs and personal builds still carry
the semicolon form. Read as a single pair it fails the first env cast and takes the
build down with it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants